/**
 * @ Author: luoqi
 * @ Create Time: 2024-11-27 10:32
 * @ Modified by: luoqi
 * @ Modified time: 2025-02-11 21:09
 * @ Description:
 */

#include "statistics.h"

static inline qfp_t _fsqrt(qfp_t x)
{
    union {
        qfp_t f;
        int i;
    } conv;
	qfp_t x2;
	x2 = x * 0.5f;
    conv.f = x;
    conv.i = 0x5f3504f3 - (conv.i >> 1);
    x = conv.f;
    x = x * (1.5f - (x2 * x * x)); // 1st iteration
    x = x * (1.5f - (x2 * x * x)); // 2nd iteration
    x = x * (1.5f - (x2 * x * x)); // 3nd iteration

    return 1.0f / x;
}


int rms_init(RmsObj *obj, uint32_t times)
{
    if(!obj || times == 0) {
        return -1;
    }
    obj->sum = 0;
    obj->cnt = 0;
    obj->rms = 0;
    obj->times = times;
    return 0;
}

qfp_t rms_update(RmsObj *obj, qfp_t data)
{
    if(!obj) {
        return 0;
    }
    obj->sum += data * data;
    obj->cnt++;
    if(obj->cnt >= obj->times) {
        obj->rms = _fsqrt(obj->sum / obj->times);
        obj->sum = 0;
        obj->cnt = 0;
    }
    return obj->rms;
}

qfp_t rms_calc(qfp_t *data, uint32_t size)
{
    if(!data || size == 0) {
        return 0;
    }
    qfp_t sum = 0;
    for(uint32_t i = 0; i < size; i++) {
        sum += data[i] * data[i];
    }
    return _fsqrt(sum / size);
}

int avg_init(AvgObj *obj, uint32_t times)
{
    obj->sum = 0;
    obj->cnt = 0;
    obj->avg = 0;
    obj->times = times;
    return 0;
}

qfp_t avg_update(AvgObj *obj, qfp_t data)
{
    if(!obj) {
        return 0;
    }
    obj->sum += data;
    obj->cnt++;
    if(obj->cnt >= obj->times) {
        obj->avg = obj->sum / obj->times;
        obj->sum = 0;
        obj->cnt = 0;
    }
    return obj->avg;
}

qfp_t avg_calc(qfp_t *data, uint32_t size)
{
    if(!data || size == 0) {
        return 0;
    }
    qfp_t sum = 0;
    for(uint32_t i = 0; i < size; i++) {
        sum += data[i];
    }
    return sum / size;
}
